﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using AviewLightSource;
using FinalTestMachine.Connect;
using FinalTestMachine.Motion.Aixs;
using FinalTestMachine.Motion.IO;
using FinalTestMachine.Motion.Product;

namespace FinalTestMachine.Motion.Process
{
    /// <summary>
    /// 每工位测试站的基类
    /// 若继承此类，请在StaticInitial的StaticInitial方法内部按顺序实例化
    /// </summary>
    public abstract class Process_TestStationBase : RM_dll2.Process.ProcessBase, RM_dll2.Process.IPause
    {
        public Process_TestStationBase(SiteUdpConnectBase siteUdpConnectBase, string name, int siteIndex) : base(name, StaticInitial.Motion, true)
        {
            connectBase = siteUdpConnectBase;
            SiteIndex = siteIndex;
            Motion.AddIPause(this);
            testStaionList.Insert(siteIndex,this);
        }


        /// <summary>
        /// 存储测试站流程对象，外部只读不写
        /// </summary>
        public static List<Process_TestStationBase> testStaionList  { get; private set; } = new List<Process_TestStationBase>(GlobalParams.WorkstationSum);


        private bool IsPause = false;

        protected bool _needAlarm = false;

        public bool IsTesting { get; protected set; }

        public abstract bool AxiOrCylinderToWorkPos();

        public abstract bool AxiOrCylinderToWaitPos();

        public abstract bool OtherActionBeforeExit();

        
        /// <summary>
        /// 当前工位是哪一个
        /// </summary>
        public string LocalStation => RotatedMovNextHelper.tagPos[SiteIndex];

        /// <summary>
        /// 通讯对象
        /// </summary>
        public SiteUdpConnectBase connectBase { get; }

        /// <summary>
        /// 站位索引
        /// </summary>
        public int SiteIndex { get; }

        /// <summary>
        /// 是否测试OK
        /// </summary>
        public bool IsTestOK { get; set; }

        /// <summary>
        /// 测试超时时间
        /// </summary>
        public static int TestOutTime => OtherParamHelper.Cur.TestOutTime.GetValue;

        /// <summary>
        /// 连续测试不良数
        /// </summary>
        public static int NgMaxNum => OtherParamHelper.Cur.ErrContinueNum.GetValue;

        /// <summary>
        /// 测试所花费时间
        /// </summary>
        public double TestTime { get; protected set; } = 0;

        /// <summary>
        /// 测试开始时间
        /// </summary>
        public string StartTime { get; set; }

        /// <summary>
        /// 测试结束时间
        /// </summary>
        public string EndTime { get; set; }

        /// <summary>
        /// 当前测试的NG数
        /// </summary>
        public int NgNums { get; protected set; }

        /// <summary>
        /// 当前测试的产品
        /// </summary>
        public ProductInfo CurrentProduct { get; private set; }

        /// <summary>
        /// 装载要测试的产品
        /// </summary>
        /// <param name="productInfo"></param>
        public void LoadProduct(ProductInfo productInfo)
        {
            CurrentProduct = productInfo;
        }

        public abstract ProductTestStation GetCurrentStation();
        public abstract ProductTestStation GetLastStation();

        /// <summary>
        /// 先检查治具是否被禁用，再判断当前站是否被禁用，最后判断当前产品是否ng
        /// </summary>
        protected override sealed void ImplementRunAction()
        {
            TestTime = 0;

            try
            {
                //判断当前治具是否被禁用
                if (CheckCurrentSiteCanUse())
                {
                    if (CurrentProduct != null)
                    {
                        GetCurrentStation().TestStationName = Name;
                        ReportMsg($"{Name}:有产品载入，开始测试");
                        //执行判断当前测试站是否被禁用
                        if (IsStationLimit())
                        {
                            ReportMsg($"{Name}：测试站禁用，跳出测试");
                            GetCurrentStation().Result = Product.TestResult.Limited;
                            return;
                        }
                        //测试站未被禁用
                        else
                        {
                            GetCurrentStation().StartTime = GetTimeNow();
                            if (Funs.FunStationSettings.Cur.IsMust)
                            {
                                TESTANDDEALACTION();
                            }
                            else
                            {
                                //每站依据上站测试结果测试
                                switch (GetLastStation().Result)
                                {
                                    case Product.TestResult.OK://上一站OK,才开始测试
                                        TESTANDDEALACTION();
                                        break;

                                    case Product.TestResult.NG://上一站Ng,本站不测试，只记录相关信息
                                        GetCurrentStation().Result = Product.TestResult.NoTest;
                                        break;

                                    case Product.TestResult.NoTest://上一站未测试,本站也不测试，只记录相关信息
                                        GetCurrentStation().Result = Product.TestResult.NoTest;
                                        break;

                                    case Product.TestResult.Limited://上站禁用直接测试
                                        if (CurrentProduct.Result != Product.ProductInfo.ResultNG)
                                        {
                                            TESTANDDEALACTION();
                                        }
                                        else
                                        {
                                            GetCurrentStation().Result = Product.TestResult.NoTest;
                                        }
                                        break;
                                }
                            }
                            GetCurrentStation().EndTime = GetTimeNow();
                            GetCurrentStation().TotalTime = TestTime;
                        }
                    }
                }
                else
                {
                    ReportMsg($"{Name}:该工位当前载具被屏蔽，直接跳出测试");
                }
            }
            catch (Exception ex)
            {
                ReportMsg($"{Name}测试异常");
                WriteErrToUser(ex.Message);
                WriteErrToUser($"{Name}出现异常，异常信息详细信息:{AM.Tools.ExceptionHelper.GetInnerExceptionMessage(ex)}");
            }
        }

        public string CyErrInfo;
        private void TESTANDDEALACTION()
        {
            //正在测试中标志
            IsTesting = true;
            TestStart();
            IsTesting = false;

            if (IsTestOK)
            {
                GetCurrentStation().Result = Product.TestResult.OK;
            }
            else
            {
                GetCurrentStation().Result = Product.TestResult.NG;
                CurrentProduct.Result = Product.ProductInfo.ResultNG;
            }
        }

        public void TestStart(bool IsTestRun = false)
        {
            IsTestOK = false;
            if (!Motion.CurOrder.IsResOK)
            {
                throw new Exception("机器未复位");
            }
            StartTime = GetTimeNow();
            DateTime dateTime = DateTime.Now;
            string error = string.Empty;
            Ref_Step("OpenCurrentAndLight");

            if (IsTestRun)
            {
                IsProcessRunning = true;
            }
            try
            {
                while (true)
                {
                    if (!IsProcessRunning)
                    {
                        break;
                    }
                    WaitPause();
                    switch (Step)
                    {
                        case "OpenCurrentAndLight":
                            PowerON();
                            Ref_Step("CylinderAndAxisGoToWorkPos");
                            break;

                        case "CylinderAndAxisGoToWorkPos":
                            try
                            {
                                if (AxiOrCylinderToWorkPos())
                                {
                                    Ref_Step("NotifyTest");
                                }
                            }
                            catch(Exception e)
                            {
                                WriteErrToUser(e.Message);
                            }
                            
                            break;

                        case "NotifyTest":
                            try
                            {
                                if (SendTestToStart())
                                {
                                    dateTime = DateTime.Now;
                                    Ref_Step("WaitTestResult");
                                }
                            }
                            catch (Exception e) {
                                WriteErrToUser(e.Message);
                            }

                            break;

                        case "WaitTestResult":
                            //测试超时判断
                            if (Funs.FunCommSelection.Cur.IsSiteTestTimeOutAlarm)
                            {
                                if ((DateTime.Now - dateTime).TotalSeconds > OtherParamHelper.Cur.TestOutTime.GetValue)
                                {
                                    WriteErrToUser($"{Name}测试等待超时！！！！");
                                    break;
                                }
                            }

                            //测试完成判断（这是一个通讯帮助类）
                            if (connectBase.IsFinished)
                            {
                                WriteToUser("收到测试结果");
                                IsTestOK = connectBase.IsOk;
                                if (CurrentProduct != null)
                                {
                                    WriteToUser("产品信息不为空");
                                    GetCurrentStation()?.StationTestItems?.Clear();

                                    //拷贝数据
                                    foreach (var item in connectBase.TestItemList)
                                    {
                                        GetCurrentStation()?.StationTestItems?.Add(new ProductTestStationTestItem(item));
                                    }

                                    //清空通讯帮助类里面的测试数据
                                    connectBase.TestItemList?.Clear();
                                    WriteToUser($"共计转移数据{GetCurrentStation()?.StationTestItems?.Count}条", System.Windows.Media.Brushes.Green, true);
                                }
                                
                                if (Motion.CurOrder.IsAutoRunning)
                                {
                                    if (!IsTestOK)
                                    {
                                        NgNums++;
                                        if (NgNums > NgMaxNum)
                                        {
                                            //连续测试不良
                                            NgNums = 0;
                                            WriteErrToUser("测试：连续测试不良!!!");
                                        }
                                    }
                                    else
                                    {
                                        if (NgNums > 1)
                                        {
                                            NgNums -= 2;
                                        }
                                        else
                                        {
                                            NgNums = 0;
                                        }
                                    }
                                }

                                Ref_Step("CylinderAndAxisGoToWaitPos");
                            }
                            break;

                        case "CylinderAndAxisGoToWaitPos":
                            try
                            {
                                if (AxiOrCylinderToWaitPos())
                                {
                                    Ref_Step("Exit");
                                }
                            }
                            catch (Exception ex) { 
                                WriteErrToUser(ex.Message);
                            }
                            
                            break;

                        case "Exit":
                            try
                            {
                                if (OtherActionBeforeExit())
                                {
                                    PowerOFF();
                                    IsProcessRunning = false;
                                }
                            }catch(Exception e)
                            {
                                WriteErrToUser($"{e.Message}");
                            }
                            
                            break;
                    }
                    Sleep(100);
                }
            }
            catch (Exception ex)
            {
                IsTesting = false;
                ReportMsg(Name + "测试失败");
                WriteErrToUser("测试：" + ex.Message);
                WriteErrToUser($"{Name}出现异常，异常信息详细信息:{AM.Tools.ExceptionHelper.GetInnerExceptionMessage(ex)}");
            }
            finally
            {
                IsTesting = false;
                TestTime = (DateTime.Now - dateTime).TotalSeconds;
                ReportMsg(Name + "Exit通知流程");
            }
        }
        /// <summary>
        /// 测试站是否禁用
        /// </summary>
        /// <returns></returns>
        public bool IsStationLimit()
        {
            string fieldName = "Site" + (SiteIndex + 1) + "IsUse";
            return !GlobalParams.GetFieldValue<bool>(Funs.FunStationSettings.Cur, fieldName);
        }

        public override void Stop()
        {
            base.Stop();
            IsErr = false;
            IsTesting = false;
        }

        public bool SendTestToStart()
        {
            try
            {
                if (((TCPHelper3.ConnectServerHelperT<UdpWpfDemo3.MTP>)connectBase.Connect).remoteClientList.Count < 1)
                {
                    WriteErrToUser($"{this.Name}与测试软件通讯未连接！");
                    return false;
                }

                RotatedMovNextHelper.Ref_Wait();
                string SN = "";
                string location = "";
                string socket = "";
                //当前站对应的治具
                location = LocalStation;
                if (Motion.CurOrder.IsAutoRunning && CurrentProduct != null)
                {
                    SN = CurrentProduct.Number;
                }
                else
                {
                    SN = "12345678";
                }
                connectBase.SendToStart(SN, location, socket);
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void SendToNotTest()
        {
            RotatedMovNextHelper.Ref_Wait();
            string SN = "";
            string location = "";
            string socket = "";
            location = LocalStation;
            if (Motion.CurOrder.IsAutoRunning)
            {
                SN = CurrentProduct.Number;
            }
            else
            {
                SN = DateTime.Now.ToString("yyyyMMddTHHmmss");
            }

            connectBase.SendToNotTest(SN, location, socket);
        }

        public string GetTimeNow()
        {
            return DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
        }

        public void WaitPause()
        {
            if (CheckPause())
            {
                while (CheckPause())
                {
                    Sleep(100);
                }
            }
        }

        public bool CheckPause()
        {
            return IsErr || Motion.CurOrder.IsErrPause || Motion.CurOrder.IsPause || IsPause;
        }

        public void Pause()
        {
            IsPause = true;
        }

        public void CanclePause()
        {
            IsPause = false;
        }

        public void PowerON()
        {
            switch (LocalStation)
            {
                case "A":
                    StaticIOHelper.Out_Power1Channel1.Out_ON();
                    IsOff[0] = false;
                    WriteToUser("A载具1_1采集卡ON");
                    break;

                case "B":
                    StaticIOHelper.Out_Power1Channel2.Out_ON();
                    IsOff[1] = false;
                    WriteToUser("B载具1_2采集卡ON");
                    break;

                case "C":
                    StaticIOHelper.Out_Power2Channel1.Out_ON();
                    IsOff[2] = false;
                    WriteToUser("C载具2_1采集卡ON");
                    break;

                case "D":
                    StaticIOHelper.Out_Power2Channel2.Out_ON();
                    IsOff[3] = false;
                    WriteToUser("D载具2_2采集卡ON");
                    break;

                case "E":
                    StaticIOHelper.Out_Power3Channel1.Out_ON();
                    IsOff[4] = false;
                    WriteToUser("E载具3_1采集卡ON");
                    break;

                case "F":
                    StaticIOHelper.Out_Power3Channel2.Out_ON();
                    IsOff[5] = false;
                    break;

                default:
                    break;
            }
        }

        bool[] IsOff = new bool[GlobalParams.WorkstationSum];
        public void PowerOFF()
        {
            //LocalStation会自动获取当前站位的治具号
            switch (LocalStation)
            {
                case "A":
                    StaticIOHelper.Out_Power1Channel1.Out_OFF();
                    IsOff[0] = true;
                    WriteToUser("A载具1_1采集卡OFF");
                    break;

                case "B":
                    StaticIOHelper.Out_Power1Channel2.Out_OFF();
                    IsOff[1] = true;
                    WriteToUser("B载具1_2采集卡OFF");
                    break;

                case "C":
                    StaticIOHelper.Out_Power2Channel1.Out_OFF();
                    IsOff[2] = true;
                    WriteToUser("C载具2_1采集卡OFF");
                    break;

                case "D":
                    WriteToUser("D载具2_2采集卡OFF");
                    StaticIOHelper.Out_Power2Channel2.Out_OFF();
                    IsOff[3] = true;
                    break;

                case "E":
                    StaticIOHelper.Out_Power3Channel1.Out_OFF();
                    WriteToUser("E载具3_1采集卡OFF");
                    IsOff[4] = true;
                    break;

                case "F":
                    StaticIOHelper.Out_Power3Channel2.Out_OFF();
                    WriteToUser("F载具3_2采集卡OFF");
                    IsOff[5] = true;
                    break;

                default:
                    break;
            }
        }

        protected bool CheckCurrentSiteCanUse()
        {
            return Funs.FunSocketSettings.Cur.CheckSocketCanUse(LocalStation);
        }
    }
}